var MONTH_LENGTHS = new Array(31,28,31,30,31,30,31,31,30,31,30,31);
var MONTH_NAMES = new Array('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec');
//var DAY_NAMES = new Array('Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat');
var DAY_NAMES = new Array('Su', 'M', 'Tu', 'W', 'Th', 'F', 'Sa');

Date.prototype.dateAdd = function(size,value) {
    value = parseInt(value);
    var incr = 0;
    switch (size) {
        case 'day':
            incr = value * 24;
            this.dateAdd('hour',incr);
            break;
        case 'hour':
            incr = value * 60;
            this.dateAdd('minute',incr);
            break;
        case 'week':
            incr = value * 7;
            this.dateAdd('day',incr);
            break;
        case 'minute':
            incr = value * 60;
            this.dateAdd('second',incr);
            break;
        case 'second':
            incr = value * 1000;
            this.dateAdd('millisecond',incr);
            break;
        case 'month':
            value = value + this.getUTCMonth();
            if (value/12>0) {
                this.dateAdd('year',value/12);
                value = value % 12;
            }
            this.setUTCMonth(value);
            break;
        case 'millisecond':
            this.setTime(this.getTime() + value);
            break;
        case 'year':
            this.setFullYear(this.getUTCFullYear()+value);
            break;
        default:
            throw new Error('Invalid date increment passed');
            break;
    }
}

function Calendar(startDate,changeHandler,closeHandler) {
	startDate.setHours(0,0,0,0)
    if (startDate<0) {startDate.dateAdd('year',100);}
    this.startDate = startDate;
    this.element = null;
    this.dateValue = startDate;
    this.changeEvent = changeHandler;
    this.closeEvent = closeHandler;
    this.render();
}

Calendar.prototype.render = function() {
    var pe;
    if (this.element && this.element.id && document.getElementById(this.element.id)) {
        pe = document.getElementById(this.element.id).parentNode;
        this.element.parentNode.removeChild(this.element);
    }
    tbl = document.createElement('table');
    tbl.setAttribute('className','cal');
    tbl.id = 'cal' + Math.round(500*Math.random());
    tbl.obj = this;
    this.element = tbl;
    var mrow = tbl.insertRow(0);
    mrow.className = 'dateTop';
    
    var cel = mrow.insertCell(0);
    cel.appendChild(document.createTextNode('<<'));
    cel.className='chgCal';
    cel.onclick=this.subYear;
    
    cel = mrow.insertCell(1);
    cel.appendChild(document.createTextNode('<'));
    cel.className='chgCal';
    cel.onclick=this.subMonth;
    
    cel = mrow.insertCell(2);
    cel.colSpan=(this.closeEvent==null) ? 3 : 2;
    cel.appendChild(document.createTextNode(MONTH_NAMES[this.startDate.getMonth()] + ' ' + this.startDate.getFullYear()));
    
    cel = mrow.insertCell(3);
    cel.style.textAlign='left';
    cel.appendChild(document.createTextNode('>'));
    cel.className='chgCal';
    cel.onclick=this.addMonth;
    
    cel = mrow.insertCell(4);
    cel.style.textAlign='left';
    cel.appendChild(document.createTextNode('>>'));
    cel.className='chgCal';
    cel.onclick=this.addYear;
    
    if (this.closeEvent!=null) {
		cel = mrow.insertCell(5);
		cel.appendChild(document.createTextNode('X'));
		cel.className='chgCal';
		cel.onclick=this.closeAction;
	}
    
    mrow = tbl.insertRow(1);
    mrow.className="hdr";
    for (var i=0;i<7;i++) {
        cel = mrow.insertCell(i);
        if (i==0 || i==6) {cel.setAttribute('className','day hdr end');} else {cel.setAttribute('className','day hdr');}
        cel.appendChild(document.createTextNode(DAY_NAMES[i]));
    }
    
    var tmpDate = new Date(this.startDate.getFullYear(),this.startDate.getMonth(),1);
    var nextMonth = new Date(this.startDate.getFullYear(),this.startDate.getMonth(),1);
    
    tmpDate.dateAdd('day',-tmpDate.getDay());
    tmpDate.setHours(0)
    nextMonth.dateAdd('month',1);
    while (tmpDate.getTime() <= nextMonth.getTime()) {
        var wk = tbl.insertRow(tbl.rows.length);
        wk.setAttribute('className','week');
        for (var i = 0;i<7;i++) {
            var d = wk.insertCell(i);
            if (i==0 || i==6) {d.setAttribute('className','day end');} else {d.setAttribute('className','day');}
            d.appendChild(document.createTextNode(tmpDate.getUTCDate()));
            //d.appendChild(document.createTextNode(tmpDate.getTime()));
            d.date = (1+tmpDate.getUTCMonth()) + '/' + tmpDate.getUTCDate() + '/' + tmpDate.getUTCFullYear();
            if (tmpDate.getTime()==this.startDate.getTime())
				d.className = d.className + " currentDay"
            d.onclick = this.setValue;
            tmpDate.dateAdd('day',1);
			tmpDate.setHours(0)
        }
    }
    
    //use document.getElementbyid....
    if (pe) {
        pe.appendChild(tbl); 
        this.element = document.getElementById(tbl.id);
    } else { 
        this.element = tbl;
    }
}

Calendar.prototype.setValue = function(evt) {
    var src = (evt) ? evt.target : event.srcElement;
    var obj = this.parentNode.parentNode.parentNode.obj;
    obj.dateValue = src.date;
    obj.changeEvent(src.date);
}

Calendar.prototype.closeAction = function(evt) {    
	var src = (evt) ? evt.target : event.srcElement;
    var obj = this.parentNode.parentNode.parentNode.obj;
    if (obj.closeEvent) {obj.closeEvent(obj);}
}

Calendar.prototype.changeMonth = function(val) {
    this.startDate.dateAdd('month',val);
    this.render();
}

Calendar.prototype.changeYear = function(val) {
    this.startDate.dateAdd('year',val);
    this.render();
}

Calendar.prototype.addMonth = function() {
    pCal = this;
    while (!pCal.obj) {pCal = pCal.parentNode;}
    pCal.obj.changeMonth(1);
}

Calendar.prototype.subMonth = function() {
    pCal = this;
    while (!pCal.obj) {pCal = pCal.parentNode;}
    pCal.obj.changeMonth(-1);
}

Calendar.prototype.addYear = function() {
    pCal = this;
    while (!pCal.obj) {pCal = pCal.parentNode;}
    pCal.obj.changeYear(1);
}

Calendar.prototype.subYear = function() {
    pCal = this;
    while (!pCal.obj) {pCal = pCal.parentNode;}
    pCal.obj.changeYear(-1);
}